package com.example.hot100;

import com.example.linked.ListNode;

import java.util.Deque;
import java.util.LinkedList;

public class Leetcode19_RemoveNthFromEnd {
    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next = new ListNode(3);
        head.next.next.next = new ListNode(4);
        head.next.next.next.next = new ListNode(5);

        int n = 3;

        ListNode res = new Solution().removeNthFromEnd(head, n);
        while (res != null) {
            System.out.println(res.val);
            res = res.next;
        }

    }

    static class Solution {
        /**
         * 双指针
         * @param head
         * @param n
         * @return
         */
        private ListNode removeNthFromEnd2(ListNode head, int n) {
            ListNode dummy = new ListNode(-1, head); // 引入哑结点，可以不考虑删除的是头结点的情况
            ListNode first = head, second = dummy;
            for (int i = 0; i < n; i++) { // 保证两个指针的间隔是 n - 1
                first = first.next;
            }
            // 然后同时移动两个指针直到first到链表尾部
            while (first != null) {
                first = first.next;
                second = second.next;
            }

            second.next = second.next.next; // 删除节点
            return dummy.next;
        }

        /**
         * 栈
         * @param head
         * @param n
         * @return
         */
        private ListNode removeNthFromEnd1(ListNode head, int n) {
            ListNode tmp = head;
            Deque<ListNode> stack = new LinkedList<>();
            while (tmp != null) {
                stack.push(tmp);
                tmp = tmp.next;
            }

            for (int i = 0; i < n; i++) {
                stack.pop();
            }
            if (!stack.isEmpty()) {
                ListNode pre = stack.pop();
                pre.next = pre.next.next;
                return head;
            }
            return head.next; // 删除的是第一个节点，直接返回head.next即可
        }

        public ListNode removeNthFromEnd(ListNode head, int n) {
            return removeNthFromEnd2(head, n);
        }
    }
}
